package InterfazGrafica;

import java.awt.Color;
import java.awt.Cursor;
import java.awt.geom.Point2D;
import Constantes.Constantes;
import Figuras.Circulo;
import Figuras.Cuadrado;
import Figuras.Elipse;
import Figuras.Figura;
import Figuras.Linea;
import Figuras.Rectangulo;
import JDBC.ConexionJDBCMySQL;
import java.awt.BasicStroke;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Stroke;
import java.awt.event.MouseEvent;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Line2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.LinkedList;
import java.util.Stack;
import javax.imageio.ImageIO;

public class PanelDeDibujo extends javax.swing.JPanel {

    private static final long serialVersionUID = 1L;
    private BufferedImage Dibujo;
    private boolean EstaRellenadaLaFigura = false;
    private Color ColorDelBorde;
    private Color ColorDelFondoDeLaPantalla;
    private Color ColorDelRellenoDeLaFigura;
    private Cursor CursorActual;
    private int AnchoDelBordeDeLaFigura;
    private int CoordenadasInicialesDeX, CoordenadasInicialesDeY;
    private int CoordenadasFinalesDeX, CoordenadasFinalesDeY;
    private int CoordenadaMinimaXDelPapel, CoordenadaMinimaYDelPapel;
    private int CoordenadaMaximaXDelPapel, CoordenadaMaximaYDelPapel;
    private int FiguraQueTienesQueDibujar;
    private int ModoDeDibujo;
    private int PosicionXAnteriorDelRaton;
    private int PosicionYAnteriorDelRaton;
    private LinkedList<Figura> ListaDeFiguras = new LinkedList<Figura>();
    private Figura FiguraQueSeArrastra;
    private Figura FiguraAEliminar;
    private Point2D PuntoDondeEstaUbicadaLaImagen;
    private String NombreDelDibujo;
    private String stringX = "x: ";
    private String stringY = " y: ";
    private Stack<Figura> deshacerAccion;
    private Stack<Figura> rehacerAccion;

    public PanelDeDibujo() {
        initComponents();
        fijarElModoDeDibujo(Constantes.modoNulo());
        fijarElAnchoDelBordeDeLaFigura(1);
        fijarElPuntoDondeSeVaAUbicarLaImagen(null);
        fijarElNombreDelDibujo(null);
        FiguraQueSeArrastra = null;
        FiguraAEliminar = null;
        deshacerAccion = new Stack<Figura>();
        rehacerAccion = new Stack<Figura>();
        fijarElColorDelBorde(Color.BLACK);
        fijarElColorDelRellenoDeLaFigura(null);
        fijarElColorDelFondoDeLaPantalla(Color.WHITE);
        setBackground(dameElColorDelFondoDeLaPantalla());
    }

    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        RehacerDeshacer = new javax.swing.JDialog();
        RehacerDeshacer_TextoInformativo = new javax.swing.JLabel();
        RehacerDeshacer_Aceptar = new javax.swing.JButton();

        RehacerDeshacer.setLocationByPlatform(true);
        RehacerDeshacer.setMinimumSize(new java.awt.Dimension(400, 150));
        RehacerDeshacer.setResizable(false);

        RehacerDeshacer_TextoInformativo.setFont(new java.awt.Font("Arial Black", 2, 12));
        RehacerDeshacer_TextoInformativo.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        RehacerDeshacer_TextoInformativo.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);

        RehacerDeshacer_Aceptar.setText("Aceptar");
        RehacerDeshacer_Aceptar.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                RehacerDeshacer_AceptarActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout RehacerDeshacerLayout = new javax.swing.GroupLayout(RehacerDeshacer.getContentPane());
        RehacerDeshacer.getContentPane().setLayout(RehacerDeshacerLayout);
        RehacerDeshacerLayout.setHorizontalGroup(
            RehacerDeshacerLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(RehacerDeshacerLayout.createSequentialGroup()
                .addContainerGap()
                .addGroup(RehacerDeshacerLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(RehacerDeshacer_TextoInformativo, javax.swing.GroupLayout.DEFAULT_SIZE, 390, Short.MAX_VALUE)
                    .addGroup(RehacerDeshacerLayout.createSequentialGroup()
                        .addComponent(RehacerDeshacer_Aceptar, javax.swing.GroupLayout.DEFAULT_SIZE, 380, Short.MAX_VALUE)
                        .addContainerGap())))
        );
        RehacerDeshacerLayout.setVerticalGroup(
            RehacerDeshacerLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(RehacerDeshacerLayout.createSequentialGroup()
                .addContainerGap()
                .addComponent(RehacerDeshacer_TextoInformativo, javax.swing.GroupLayout.PREFERRED_SIZE, 55, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(RehacerDeshacer_Aceptar)
                .addContainerGap())
        );

        setBackground(new java.awt.Color(255, 255, 255));
        setMinimumSize(new java.awt.Dimension(1200, 1200));
        setPreferredSize(new java.awt.Dimension(810, 471));
        addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                formMouseClicked(evt);
            }
            public void mouseEntered(java.awt.event.MouseEvent evt) {
                formMouseEntered(evt);
            }
            public void mouseExited(java.awt.event.MouseEvent evt) {
                formMouseExited(evt);
            }
            public void mousePressed(java.awt.event.MouseEvent evt) {
                formMousePressed(evt);
            }
            public void mouseReleased(java.awt.event.MouseEvent evt) {
                formMouseReleased(evt);
            }
        });
        addMouseMotionListener(new java.awt.event.MouseMotionAdapter() {
            public void mouseDragged(java.awt.event.MouseEvent evt) {
                formMouseDragged(evt);
            }
            public void mouseMoved(java.awt.event.MouseEvent evt) {
                formMouseMoved(evt);
            }
        });

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
        this.setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 810, Short.MAX_VALUE)
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 471, Short.MAX_VALUE)
        );
    }// </editor-fold>//GEN-END:initComponents

    private void formMousePressed(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_formMousePressed
        fijarCoordenadasInicialesDeX(evt.getX());
        fijarCoordenadasInicialesDeY(evt.getY());
        fijarLaCoordenadaXMinimaDelPapel(evt.getX());
        fijarLaCoordenadaYMinimaDelPapel(evt.getY());
        fijarLaCoordenadaXMaximaDelPapel(evt.getX());
        fijarLaCoordenadaYMaximaDelPapel(evt.getY());
        PantallaPrincipal.EtiquetaCoordenadas.setText(stringX + evt.getX() + stringY + evt.getY());
    }//GEN-LAST:event_formMousePressed

    private void formMouseReleased(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_formMouseReleased
        if (ModoDeDibujo == Constantes.modoLinea()) {
            Linea linea = new Linea(dameCoordenadasInicialesDeX(), dameCoordenadasInicialesDeY(),
                    dameCoordenadasFinalesDeX(), dameCoordenadasFinalesDeY(),
                    dameElColorDelBorde(), dameElAnchoDelBordeDeLaFigura());
            agregarFigura(linea);
            deshacerAccion.push(linea);
        } else if (ModoDeDibujo == Constantes.modoCuadrado()) {
            Cuadrado cuadrado = new Cuadrado(Math.min(dameCoordenadasInicialesDeX(), dameCoordenadasFinalesDeX()),
                    Math.min(dameCoordenadasInicialesDeY(), dameCoordenadasFinalesDeY()),
                    Math.abs(dameCoordenadasInicialesDeX() - dameCoordenadasFinalesDeX()),
                    dameElColorDelBorde(), dameElColorDelRellenoDeLaFigura(), dameElAnchoDelBordeDeLaFigura());
            agregarFigura(cuadrado);
            deshacerAccion.push(cuadrado);
        } else if (ModoDeDibujo == Constantes.modoRectangulo()) {
            Rectangulo rectangulo = new Rectangulo(Math.min(dameCoordenadasInicialesDeX(), dameCoordenadasFinalesDeX()),
                    Math.min(dameCoordenadasInicialesDeY(), dameCoordenadasFinalesDeY()),
                    Math.abs(dameCoordenadasInicialesDeX() - dameCoordenadasFinalesDeX()),
                    Math.abs(dameCoordenadasInicialesDeY() - dameCoordenadasFinalesDeY()),
                    dameElColorDelBorde(), dameElColorDelRellenoDeLaFigura(), dameElAnchoDelBordeDeLaFigura());
            agregarFigura(rectangulo);
            deshacerAccion.push(rectangulo);
        } else if (ModoDeDibujo == Constantes.modoCirculo()) {
            double radio = Math.sqrt(Math.pow(dameCoordenadasFinalesDeX() - dameCoordenadasInicialesDeX(), 2)
                    + Math.pow(dameCoordenadasFinalesDeY() - dameCoordenadasInicialesDeY(), 2));
            Circulo circulo = new Circulo(dameCoordenadasInicialesDeX(), dameCoordenadasInicialesDeY(),
                    radio, dameElColorDelBorde(),
                    dameElColorDelRellenoDeLaFigura(), dameElAnchoDelBordeDeLaFigura());
            agregarFigura(circulo);
            deshacerAccion.push(circulo);
        } else if (ModoDeDibujo == Constantes.modoElipse()) {
            Elipse elipse = new Elipse(Math.min(dameCoordenadasInicialesDeX(), dameCoordenadasFinalesDeX()),
                    Math.min(dameCoordenadasInicialesDeY(), dameCoordenadasFinalesDeX()),
                    Math.abs(dameCoordenadasInicialesDeX() - dameCoordenadasFinalesDeX()),
                    Math.abs(dameCoordenadasInicialesDeY() - dameCoordenadasFinalesDeY()),
                    dameElColorDelBorde(), dameElColorDelRellenoDeLaFigura(), dameElAnchoDelBordeDeLaFigura());
            agregarFigura(elipse);
            deshacerAccion.push(elipse);
        }
        PantallaPrincipal.EtiquetaCoordenadas.setText(stringX + evt.getX() + stringY + evt.getY());
        repaint();
    }//GEN-LAST:event_formMouseReleased

    private void formMouseDragged(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_formMouseDragged
        fijarCoordenadasFinalesDeX(evt.getX());
        fijarCoordenadasFinalesDeY(evt.getY());
        if (ModoDeDibujo == Constantes.modoArrastrar()) {
            if (FiguraQueSeArrastra == null) {
                PosicionXAnteriorDelRaton = evt.getX();
                PosicionYAnteriorDelRaton = evt.getY();
                FiguraQueSeArrastra = dameFigura(evt);
            } else {
                FiguraQueSeArrastra.fijarPosicionDeLaFigura((int) FiguraQueSeArrastra.dameElInicioDeLaFigura().getX()
                        + (evt.getX() - PosicionXAnteriorDelRaton),
                        (int) FiguraQueSeArrastra.dameElInicioDeLaFigura().getY()
                        + (evt.getY() - PosicionYAnteriorDelRaton));
                PosicionXAnteriorDelRaton = evt.getX();
                PosicionYAnteriorDelRaton = evt.getY();
                repaint();
            }
        }
        PantallaPrincipal.EtiquetaCoordenadas.setText(stringX + evt.getX() + stringY + evt.getY());
        repaint();
    }//GEN-LAST:event_formMouseDragged

    private void formMouseMoved(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_formMouseMoved
        FiguraQueSeArrastra = null;
        PantallaPrincipal.EtiquetaCoordenadas.setText(stringX + evt.getX() + stringY + evt.getY());
    }//GEN-LAST:event_formMouseMoved

    private void formMouseExited(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_formMouseExited
        fijarElCursorActual(new Cursor(Cursor.DEFAULT_CURSOR));
        PantallaPrincipal.EtiquetaCoordenadas.setText(stringX + evt.getX() + stringY + evt.getY());
    }//GEN-LAST:event_formMouseExited

    private void formMouseEntered(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_formMouseEntered
        fijarElCursorActual(dameElCursorActual());
    }//GEN-LAST:event_formMouseEntered

    private void formMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_formMouseClicked
        if (ModoDeDibujo == Constantes.modoBorrador()) {
            FiguraAEliminar = dameFigura(evt);
            eliminarFigura(FiguraAEliminar);
        }
        repaint();
    }//GEN-LAST:event_formMouseClicked

    private void RehacerDeshacer_AceptarActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_RehacerDeshacer_AceptarActionPerformed
        RehacerDeshacer.setVisible(false);
    }//GEN-LAST:event_RehacerDeshacer_AceptarActionPerformed
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JDialog RehacerDeshacer;
    private javax.swing.JButton RehacerDeshacer_Aceptar;
    private javax.swing.JLabel RehacerDeshacer_TextoInformativo;
    // End of variables declaration//GEN-END:variables

    public final String dameElNombreDelDibujo() {
        return NombreDelDibujo;
    }

    public final int dameElModoDeDibujo() {
        return ModoDeDibujo;
    }

    public final void fijarElModoDeDibujo(int modoDeDibujo) {
        this.ModoDeDibujo = modoDeDibujo;
    }

    public final void fijarElNombreDelDibujo(String nombreDelDibujo) {
        this.NombreDelDibujo = nombreDelDibujo;
    }

    public final int dameCoordenadasInicialesDeX() {
        return CoordenadasInicialesDeX;
    }

    public final void fijarCoordenadasInicialesDeX(int coordenadasIniciales) {
        if (coordenadasIniciales >= 0 && coordenadasIniciales <= Constantes.anchoPantalla()) {
            this.CoordenadasInicialesDeX = coordenadasIniciales;
        }
    }

    public final int dameCoordenadasFinalesDeX() {
        return CoordenadasFinalesDeX;
    }

    public final void fijarCoordenadasFinalesDeX(int coordenadasFinales) {
        if (coordenadasFinales >= 0 && coordenadasFinales <= Constantes.anchoPantalla()) {
            this.CoordenadasFinalesDeX = coordenadasFinales;
        }
    }

    public final int dameCoordenadasInicialesDeY() {
        return CoordenadasInicialesDeY;
    }

    public final void fijarCoordenadasInicialesDeY(int coordenadasIniciales) {
        if (coordenadasIniciales >= 0 && coordenadasIniciales <= Constantes.altoPantalla()) {
            this.CoordenadasInicialesDeY = coordenadasIniciales;
        }
    }

    public final int dameCoordenadasFinalesDeY() {
        return CoordenadasFinalesDeY;
    }

    public final void fijarCoordenadasFinalesDeY(int coordenadasFinales) {
        if (coordenadasFinales >= 0 && coordenadasFinales <= Constantes.altoPantalla()) {
            this.CoordenadasFinalesDeY = coordenadasFinales;
        }
    }

    public final Color dameElColorDelBorde() {
        return ColorDelBorde;
    }

    public final void fijarElColorDelBorde(Color colorDelBorde) {
        this.ColorDelBorde = colorDelBorde;
    }

    public final Color dameElColorDelFondoDeLaPantalla() {
        return ColorDelFondoDeLaPantalla;
    }

    public final void fijarElColorDelFondoDeLaPantalla(Color colorDelFondo) {
        this.ColorDelFondoDeLaPantalla = colorDelFondo;
    }

    public final Color dameElColorDelRellenoDeLaFigura() {
        return ColorDelRellenoDeLaFigura;
    }

    public final void fijarElColorDelRellenoDeLaFigura(Color colorDelRelleno) {
        this.ColorDelRellenoDeLaFigura = colorDelRelleno;
    }

    public final int dameElAnchoDelBordeDeLaFigura() {
        return AnchoDelBordeDeLaFigura;
    }

    public final void fijarElAnchoDelBordeDeLaFigura(int anchoDelBorde) {
        if (anchoDelBorde >= Constantes.minimoGrosor() && anchoDelBorde <= Constantes.maximoGrosor()) {
            this.AnchoDelBordeDeLaFigura = anchoDelBorde;
        }
    }

    public final Cursor dameElCursorActual() {
        return CursorActual;
    }

    public final void fijarElCursorActual(Cursor cursorAFijar) {
        this.CursorActual = cursorAFijar;
    }

    public final Point2D dameElPuntoDondeEstaUbicadaLaImagen() {
        return PuntoDondeEstaUbicadaLaImagen;
    }

    public final void fijarElPuntoDondeSeVaAUbicarLaImagen(Point2D puntoDondeSeVaAUbicar) {
        this.PuntoDondeEstaUbicadaLaImagen = puntoDondeSeVaAUbicar;
        repaint();
    }

    public final boolean saberSiLaFiguraEstaRellenada() {
        return EstaRellenadaLaFigura;
    }

    public final void fijarSiUnaFiguraSeRellenaONo(boolean tieneRelleno) {
        this.EstaRellenadaLaFigura = tieneRelleno;
    }

    public final int dameLaCoordenadaXMinimaDelPapel() {
        return CoordenadaMinimaXDelPapel;
    }

    public final void fijarLaCoordenadaXMinimaDelPapel(int coordenadaMinimaX) {
        this.CoordenadaMinimaXDelPapel = coordenadaMinimaX;
    }

    public final int dameLaCoordenadaYMinimaDelPapel() {
        return CoordenadaMinimaYDelPapel;
    }

    public final void fijarLaCoordenadaYMinimaDelPapel(int coordenadaMinimaY) {
        this.CoordenadaMinimaYDelPapel = coordenadaMinimaY;
    }

    public final int dameLaCoordenadaXMaximaDelPapel() {
        return CoordenadaMaximaXDelPapel;
    }

    public final void fijarLaCoordenadaXMaximaDelPapel(int coordenadaMaximaX) {
        this.CoordenadaMaximaXDelPapel = coordenadaMaximaX;
    }

    public final int dameLaCoordenadaYMaximaDelPapel() {
        return CoordenadaMaximaYDelPapel;
    }

    public final void fijarLaCoordenadaYMaximaDelPapel(int coordenadaMaximaY) {
        this.CoordenadaMaximaYDelPapel = coordenadaMaximaY;
    }

    public final int dimeLoQueTengoQueDibujar() {
        return FiguraQueTienesQueDibujar;
    }

    public final void fijarLoQueTengoQueDibujar(int figuraADibujar) {
        this.FiguraQueTienesQueDibujar = figuraADibujar;
    }

    public final BufferedImage dameDibujo() {
        return Dibujo;
    }

    public final void fijarDibujo(Image dibujo) {
        this.Dibujo = (BufferedImage) dibujo;
        fijarElPuntoDondeSeVaAUbicarLaImagen(null);
        repaint();
    }

    public final void fijarDibujo(File dibujo) {
        try {
            fijarDibujo(ImageIO.read(dibujo));
        } catch (IOException falloAlLeerLaImagen) {
            System.out.println(falloAlLeerLaImagen);
        }
        repaint();
    }

    public final void agregarFigura(Figura figura) {
        ListaDeFiguras.add(figura);
    }

    public final void eliminarFigura(Figura figura) {
        ListaDeFiguras.remove(figura);
    }

    public final Figura dameFigura(MouseEvent clickDelRaton) {
        Figura figuraAuxiliar = null;
        for (Figura figura : ListaDeFiguras) {
            if (figura.estaDentroDelAreaDeDibujo(clickDelRaton.getX(), clickDelRaton.getY())) {
                figuraAuxiliar = figura;
            }
        }
        return figuraAuxiliar;
    }

    public final void deshacerAccion() {
        if (deshacerAccion.isEmpty()) {
            RehacerDeshacer_TextoInformativo.setText("No hay Acciones Que Deshacer...");
            RehacerDeshacer.setVisible(true);
        } else {
            Figura figuraAEliminar = deshacerAccion.pop();
            rehacerAccion.push(figuraAEliminar);
            eliminarFigura(figuraAEliminar);
        }
        repaint();
    }

    public final void rehacerAccion() {
        if (rehacerAccion.isEmpty()) {
            RehacerDeshacer_TextoInformativo.setText("No hay Acciones Que Rehacer...");
            RehacerDeshacer.setVisible(true);
        } else {
            Figura figuraAPintar = rehacerAccion.pop();
            deshacerAccion.push(figuraAPintar);
            agregarFigura(figuraAPintar);
        }
        repaint();
    }

    public void abrirDibujo(String NombreDelDibujo) {
        ConexionJDBCMySQL.sacarImagenBBDD(NombreDelDibujo);
        String ruta = ConexionJDBCMySQL.dameElDirectorioTemporalDelSistema()
                + ConexionJDBCMySQL.dameLaBarraDelSistema() + NombreDelDibujo
                + ConexionJDBCMySQL.dameElFormatoDeLaImagen();
        File imagen = new File(ruta);
        try {
            Dibujo = ImageIO.read(imagen);
        } catch (IOException falloAlLeerLaImagen) {
            System.out.println(falloAlLeerLaImagen);
        }
        fijarDibujo(Dibujo);
        Graphics grafico = Dibujo.getGraphics();
        fijarElColorDelFondoDeLaPantalla(Color.WHITE);
        fijarElNombreDelDibujo(NombreDelDibujo + "_1");
        grafico.drawImage(Dibujo, 0, 0, this);
        repaint();
    }

    public void guardarDibujo() {
        File archivo = new File(ConexionJDBCMySQL.dameElDirectorioTemporalDelSistema()
                + ConexionJDBCMySQL.dameLaBarraDelSistema() + dameElNombreDelDibujo()
                + ConexionJDBCMySQL.dameElFormatoDeLaImagen());
        if (Dibujo == null) {
            crearDibujo();
        }
        try {
            ImageIO.write(dameDibujo(), "png", archivo);
        } catch (IOException noSeHaPodidoGuardarElFichero) {
            System.out.println(noSeHaPodidoGuardarElFichero);
        }
        ConexionJDBCMySQL.guardarImagenEnBBDD(dameElNombreDelDibujo());
        ConexionJDBCMySQL.borrarImagenDeDisco(dameElNombreDelDibujo());
        ListaDeFiguras.clear();
        deshacerAccion.clear();
        rehacerAccion.clear();
        fijarElModoDeDibujo(Constantes.modoNulo());
        repaint();
    }

    public void crearDibujo() {
        Dibujo = new BufferedImage(this.getWidth(), this.getHeight(), BufferedImage.TYPE_INT_RGB);
        Graphics2D grafico2D = Dibujo.createGraphics();
        grafico2D.setColor(dameElColorDelFondoDeLaPantalla());
        grafico2D.fillRect(0, 0, this.getWidth(), this.getHeight());
        dibujarFiguras(grafico2D);
        fijarDibujo(Dibujo);
        grafico2D.dispose();
        fijarDibujo(Dibujo);
    }

    @Override
    public void paint(Graphics grafico) {
        super.paintComponent(grafico);
        Graphics2D grafico2D;
        setBackground(dameElColorDelFondoDeLaPantalla());
        if (dameDibujo() != null) {
            Point2D centro = new Point2D.Double(getWidth() / 2, getHeight() / 2);
            if (dameElPuntoDondeEstaUbicadaLaImagen() != null) {
                centro = dameElPuntoDondeEstaUbicadaLaImagen();
            }
            Point2D localizacion = new Point2D.Double();
            double width = Dibujo.getWidth();
            double height = Dibujo.getHeight();
            localizacion.setLocation(centro.getX() - (width / 2), centro.getY() - (height / 2));
            fijarElColorDelFondoDeLaPantalla(dameElColorDelFondoDeLaPantalla());
            grafico.drawImage(dameDibujo(), (int) localizacion.getX(), (int) localizacion.getY(),
                    (int) width, (int) height, null);
        }
        dibujarFiguras(grafico);
        this.setBackground(dameElColorDelFondoDeLaPantalla());
        grafico.setColor(dameElColorDelBorde());
        if (ModoDeDibujo != Constantes.modoArrastrar()) {
            if (ModoDeDibujo == Constantes.modoLinea()) {
                Line2D linea = new Line2D.Float(dameCoordenadasInicialesDeX(),
                        dameCoordenadasInicialesDeY(), dameCoordenadasFinalesDeX(),
                        dameCoordenadasFinalesDeY());
                grafico2D = (Graphics2D) grafico;
                Stroke bordeDeLinea = new BasicStroke(dameElAnchoDelBordeDeLaFigura(),
                        BasicStroke.CAP_ROUND, BasicStroke.JOIN_MITER);
                grafico2D.setColor(dameElColorDelBorde());
                grafico2D.setStroke(bordeDeLinea);
                grafico2D.draw(linea);
            }
            if (ModoDeDibujo == Constantes.modoCuadrado()) {
                if (EstaRellenadaLaFigura) {
                    grafico.setColor(dameElColorDelRellenoDeLaFigura());
                    grafico.fillRect(Math.min(dameCoordenadasInicialesDeX(), dameCoordenadasFinalesDeX()),
                            Math.min(dameCoordenadasInicialesDeY(), dameCoordenadasFinalesDeY()),
                            Math.abs(dameCoordenadasInicialesDeX() - dameCoordenadasFinalesDeX()),
                            Math.abs(dameCoordenadasInicialesDeY() - dameCoordenadasFinalesDeY()));
                }
                Rectangle2D cuadrado;
                Stroke bordeDelCuadrado;
                cuadrado = new Rectangle2D.Float(Math.min(dameCoordenadasInicialesDeX(), dameCoordenadasFinalesDeX()),
                        Math.min(dameCoordenadasInicialesDeY(), dameCoordenadasFinalesDeY()),
                        Math.abs(dameCoordenadasInicialesDeX() - dameCoordenadasFinalesDeX()),
                        Math.abs(dameCoordenadasInicialesDeX() - dameCoordenadasFinalesDeX()));
                grafico2D = (Graphics2D) grafico;
                bordeDelCuadrado = new BasicStroke(dameElAnchoDelBordeDeLaFigura(), BasicStroke.CAP_ROUND,
                        BasicStroke.JOIN_MITER);
                grafico2D.setColor(dameElColorDelBorde());
                grafico2D.setStroke(bordeDelCuadrado);
                grafico2D.draw(cuadrado);
            }
            if (ModoDeDibujo == Constantes.modoRectangulo()) {
                if (EstaRellenadaLaFigura) {
                    grafico.setColor(dameElColorDelRellenoDeLaFigura());
                    grafico.fillRect(Math.min(dameCoordenadasInicialesDeX(), dameCoordenadasFinalesDeX()),
                            Math.min(dameCoordenadasInicialesDeY(), dameCoordenadasFinalesDeY()),
                            Math.abs(dameCoordenadasInicialesDeX() - dameCoordenadasFinalesDeX()),
                            Math.abs(dameCoordenadasInicialesDeY() - dameCoordenadasFinalesDeY()));
                }
                Rectangle2D rectangulo;
                Stroke bordeDelRectangulo;
                rectangulo = new Rectangle2D.Float(Math.min(dameCoordenadasInicialesDeX(), dameCoordenadasFinalesDeX()),
                        Math.min(dameCoordenadasInicialesDeY(), dameCoordenadasFinalesDeY()),
                        Math.abs(dameCoordenadasInicialesDeX() - dameCoordenadasFinalesDeX()),
                        Math.abs(dameCoordenadasInicialesDeY() - dameCoordenadasFinalesDeY()));
                grafico2D = (Graphics2D) grafico;
                bordeDelRectangulo = new BasicStroke(dameElAnchoDelBordeDeLaFigura(),
                        BasicStroke.CAP_ROUND, BasicStroke.JOIN_MITER);
                grafico2D.setColor(dameElColorDelBorde());
                grafico2D.setStroke(bordeDelRectangulo);
                grafico2D.draw(rectangulo);
            }
            if (ModoDeDibujo == Constantes.modoCirculo()) {
                double radio = Math.sqrt(Math.pow(dameCoordenadasFinalesDeX() - dameCoordenadasInicialesDeX(), 2)
                        + Math.pow(dameCoordenadasFinalesDeY() - dameCoordenadasInicialesDeY(), 2));
                if (EstaRellenadaLaFigura) {
                    grafico.setColor(dameElColorDelRellenoDeLaFigura());
                    grafico.fillOval(dameCoordenadasInicialesDeX() - (int) radio,
                            dameCoordenadasInicialesDeY() - (int) radio,
                            (int) radio * 2,
                            (int) radio * 2);
                }
                Ellipse2D circulo;
                Stroke bordeDelCirculo;
                circulo = new Ellipse2D.Float(dameCoordenadasInicialesDeX() - (int) radio,
                        dameCoordenadasInicialesDeY() - (int) radio,
                        (int) radio * 2,
                        (int) radio * 2);
                grafico2D = (Graphics2D) grafico;
                bordeDelCirculo = new BasicStroke(dameElAnchoDelBordeDeLaFigura(),
                        BasicStroke.CAP_ROUND, BasicStroke.JOIN_MITER);
                grafico2D.setColor(dameElColorDelBorde());
                grafico2D.setStroke(bordeDelCirculo);
                grafico2D.draw(circulo);
            }
            if (ModoDeDibujo == Constantes.modoElipse()) {
                if (EstaRellenadaLaFigura) {
                    grafico.setColor(dameElColorDelRellenoDeLaFigura());
                    grafico.fillOval(Math.min(dameCoordenadasInicialesDeX(), dameCoordenadasFinalesDeX()),
                            Math.min(dameCoordenadasInicialesDeY(), dameCoordenadasFinalesDeY()),
                            Math.abs(dameCoordenadasInicialesDeX() - dameCoordenadasFinalesDeX()),
                            Math.abs(dameCoordenadasInicialesDeY() - dameCoordenadasFinalesDeY()));
                }
                Ellipse2D elipse;
                Stroke bordeDeLaElipse;
                elipse = new Ellipse2D.Float(Math.min(dameCoordenadasInicialesDeX(), dameCoordenadasFinalesDeX()),
                        Math.min(dameCoordenadasInicialesDeY(), dameCoordenadasFinalesDeY()),
                        Math.abs(dameCoordenadasInicialesDeX() - dameCoordenadasFinalesDeX()),
                        Math.abs(dameCoordenadasInicialesDeY() - dameCoordenadasFinalesDeY()));
                grafico2D = (Graphics2D) grafico;
                bordeDeLaElipse = new BasicStroke(dameElAnchoDelBordeDeLaFigura(),
                        BasicStroke.CAP_ROUND, BasicStroke.JOIN_MITER);
                grafico2D.setColor(dameElColorDelBorde());
                grafico2D.setStroke(bordeDeLaElipse);
                grafico2D.draw(elipse);
            }
        }
    }

    public void dibujarFiguras(Graphics grafico) {
        for (Figura figura : ListaDeFiguras) {
            figura.dibujarLaFigura(grafico);
        }
    }
}
